<?php

/**
 * Pagination handler.
 *
 * @author Ian Clarence <ian.clarence@gmail.com>
 */
class Pagination {

    /**
     * Default row count for each page.
     */
    const ROW_COUNT = 10;

    /**
     * Maximum number of pages in navigation.
     */
    const NAV_PAGE_COUNT = 5;

    /**
     * The data to display.
     *
     * @var array
     */
    private $rows;

    /**
     * The navigation array.
     *
     * @var array
     */
    private $navigationArray;

    /**
     * The constructor.
     * $query is the query for returning all the required data,
     * and it *must* contain LIMIT :offset, $row_count.
     * $queryCount is the query for counting the total number of possible
     * rows, and *must* contain SELECT COUNT(*) AS `count`.
     *
     * @param Query $query
     * @param Query $queryCount
     * @param int $pageNumber
     * @param int $rowCount
     * @param string $name
     */
    public function __construct(
        $query,
        $queryCount,
        $pageNumber = 1,
        $rowCount = self::ROW_COUNT,
        $name = NULL
    ) {        
        // $session = System::getSession();
        $database = System::getDB();

        /**
         * Rows: data to display.
         */
        $apcKey = 'pagination' . $name == NULL ? '_' : $name . '_' . $pageNumber;
        $params = array(
            'query' => $query, 
            'page_number' => $pageNumber, 
            'row_count' => $rowCount
        );
        $callback = function($params) {
            $offset = ($params['page_number'] - 1) * $params['row_count'];
            $params['query']->bindVariable('offset', $offset, FALSE);
            $params['query']->bindVariable('row_count', $params['row_count'], FALSE);
            return $database->queryArray($params['query']);
        };        
        $this->rows = Utils::apcCache($apcKey, $callback, STORED_AS_CACHE == YES, $params, $name != NULL);        

        /**
         * Page count.
         */
        $apcKey = 'pagination' . $name == NULL ? '_' : $name . '_pagecount';
        $params = array('query_count' => $queryCount, 'row_count' => $rowCount);
        $callback = function($params) {
            $row = $database->queryArray($params['query_count'], TRUE);
            return ceil((float) $row['count'] / $params['row_count']);
        };        
        $pageCount = Utils::apcCache($apcKey, $callback, STORED_AS_CACHE == YES, $params, $name != NULL);
        
        /**
         * Navigation array for pagination: no need if only one page.
         */
        if ($pageCount > 1) {
            $nav = array();
            $nav['to_beginning'] = $pageNumber == 1 ? NULL : 1;
            $nav['back_one'] =  $pageNumber == 1 ? NULL : $pageNumber - 1;
            for ($key = 0; $key < self::NAV_PAGE_COUNT; $key++) {
                $pgNo = $pageNumber + $key - floor(self::NAV_PAGE_COUNT / 2);
                if ($pgNo >= 1 && $pgNo <= $pageCount) {
                    $nav[$pgNo] = $pageNumber == $pgNo ? NULL : $pgNo;
                }
            }
            $nav['forward_one'] = $pageNumber == $pageCount ? NULL : $pageNumber + 1;
            $nav['to_end'] = $pageNumber == $pageCount ? NULL : $pageCount;
            $this->navigationArray = $nav;
        }
        else {
            $this->navigationArray = NULL;
        }

    }

    /**
     * Getting the data to display.
     *
     * @return array
     */
    public function getRows() {
        return $this->rows;
    }

    /**
     * Getting the navigation array.
     * 
     * @return array
     */
    public function getNavigationArray() {
        return $this->navigationArray;
    }

}